/**
 * This class is the implementation base for CORBA implementation.
 *
 *
 * @author	Jerome DANIEL.
 */
package org.omg.CORBA;

import com.cognition.util.j2me.ApplicationProperties;
import com.cognition.util.j2me.Properties;

abstract public class ORB {

    /**
     * Properties fed to the ORB through the call to init().
     */
    private static Properties _init_properties;

    /**
     * Application properties used by various methods.  Allows retrieval
     * of properties from the common sources: System, JAD and Manifest.
     */
    private static ApplicationProperties _properties;


    /** This is the property name of the ORB implementation provided by this
     * library.  It can be set in a Properties object and passed to the ORB
     * constructor..  The ORB initialization
     * routine ORB.init() will use it if it is set.
     */
    public static final String ORB_CLASS_KEY = "org.omg.CORBA.ORBClass";
    /** This is the property name of the ORB singleton used by this implementation.
     * It can be set in a Properties object and passed to the ORB constructor.
     * The ORB initialization routine ORB.init() will use it if it is set.
     */
    public static final String ORB_SINGLETON_CLASS_KEY = "org.omg.CORBA.ORBSingletonClass";
    /**
     * The last resort fallback ORB implementation classes in case
     * no ORB implementation class is dynamically configured through
     * properties or applet parameters. Change these values to
     * vendor-specific class names.
     */
    public static final String ORB_DEFAULT_CLASS = "org.huihoo.orbas.orb.ORB";
    /**
     * The last resort fallback ORB singleton classes in case
     * no ORB singleton class is dynamically configured through
     * properties. Change these values to
     * vendor-specific class names.
     */
    public static final String ORB_SINGLETON_DEFAULT_CLASS =
            "org.huihoo.orbas.orb.ORBSingleton";
    /**
     * A reference to the singleton
     */
    private static org.omg.CORBA.ORB _singleton;

    public void destroy() {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public static ApplicationProperties getApplicationProperties(){
        if (_properties == null)
            _properties = new ApplicationProperties();
        return _properties;
    }

    public static Properties getOrbProperties(){
        return _init_properties;
    }

    /**
     * Returns a property value if it exists from the following sources in
     * the following order:
     * <ol>
     * <li>From the properties object that was passed to init, if any.
     * <li>From the application properties object.
     * @param key the key to look up
     * @return the value associated with the key, or null of the key doesn't exist.
     */
    public static String getProperty(String key){
        String result = null;

        if (_init_properties != null)
            result = _init_properties.get(key);

        if (result != null)
            return result;

        return getApplicationProperties().getProperty(key);

    }

    /**
     * Returns the ORB singleton for this implementation.  On first
     * invocation, the singleton is created.  Attempts to determine the orb class
     * name by reading property {@link #ORB_SINGLETON_CLASS_KEY ORB_SINGLETON_CLASS_KEY} from
     * application properties.  If that property
     * is not set than the orb class defined in {@link #defaultORB defaultORB}
     * is used.
     */
    public static ORB getSingletonOrb() {
        
        
        if (_singleton == null) {
            // in the original implementation, the ORB_CLASS_KEY is used
            // for the singleton.  That's not correct.  The singleton class
            // is supposed to have reduced functionality.
            String className =
                    getApplicationProperties().getProperty(ORB_SINGLETON_CLASS_KEY);

            if (className == null) {
                className = ORB_SINGLETON_DEFAULT_CLASS;
            }

            try {
                _singleton = (ORB) Class.forName(className).newInstance();
            } catch (Exception ex) {
                throw new INITIALIZE("can't instantiate ORB implementation " + className);
            }
        }
        return _singleton;
    }

    /**
     * This call returns the singleton ORB. The purpose of this ORB, according to
     * some documentation on CORBA implementations, is to allow an application
     * access to a singleton ORB instance to perform limited functions, like
     * returning typecodes.
     *
     * <p>In this implementation, however, there typically isn't a difference between
     * the singleton ORB and a non-singleton ORB.  Primarily, the singleton ORB can
     * be a different class than the non-singleton ORB.  In future versions of
     * OrbasJ2ME, this may be the case.  The singleton orb class is set by system
     * properties (see getSingletonORB), so a developer can create a singleton ORB
     * that can have different functionality than a non-singleton, fully functional ORB.
     * I think one of the key differences between the two types of ORB is that the
     * singleton ORB won't be bound to a socket or allow that to happen, which allows
     * an implementation to perform local function calls that dont impact the network.
     *
     * <p>See http://download.oracle.com/docs/cd/E13211_01/wle/jref/jprorb.htm
     * for more information.  Here is an excerpt from that documentation:
     *
     * <blockquote>
     * The following code fragment creates an ORB object initialized with the default ORB Singleton. This ORB has a restricted implementation to prevent malicious applets from doing anything beyond creating typecodes. It is called a Singleton because there is only one instance for an entire virtual machine.

            ORB orb = ORB.init();

        The following code fragment creates an ORB object and a Singleton ORB object for an application.

            Properties p = new Properties();
            p.put("org.omg.CORBA.ORBClass", "com.sun.CORBA.iiop.ORB");
            p.put("org.omg.CORBA.ORBSingletonClass","com.sun.CORBA.idl.ORBSingleton");
            System.setProperties(p);
            ORB orb = ORB.init(args, p);

        In the preceding code fragment, note the following:

            * The ORB class is to be initialized as com.sun.CORBA.iiop.ORB.

            * The SingletonORB class is to be initialized as com.sun.CORBA.idl.ORBSingleton.

            * The statement System.setProperties(p) sets the system properties based on the value of p.

            * The parameter args represents the arguments supplied to the application's main method. If p is null, and the arguments do not specify an ORB class, the new ORB is initialized with the default Java IDL implementation.

              Note: Due to the security restrictions on applets, you will probably not be able to invoke the System.setProperties method from within an applet. Instead, you can set the org.omg.CORBA.ORBClass and org.omg.CORBA.ORBSingletonClass parameters via HTML before starting the applet.

        The following code fragment creates an ORB object for the applet supplied as the first parameter. If the given applet does not specify an ORB class, the new ORB will be initialized with the default BEA WebLogic Enterprise ORB implementation.
     * </blockquote>
     * @return
     */
    public static ORB init(){
        return getSingletonOrb();
    }

    /**
     * Initializes an ORB and leaves the singleton class alone. If the
     * specified orbClass name is left null, then the default orb class
     * (ORB_CLASS_KEY) is used.
     * @return a new ORB created with the specified name.
     */
    private static ORB initOrb(String orbClass) {

        String className = orbClass != null ? orbClass :
            getApplicationProperties().getProperty(ORB_CLASS_KEY);

        if (className == null) {
            className = ORB_DEFAULT_CLASS;
        }

        try {
            return (ORB) Class.forName(className).newInstance();
        } catch (Exception ex) {
            throw new INITIALIZE("can't instantiate ORB implementation " + className);
        }
    }

    /**
     * Create a new ORB that can be used for server side work. The
     * ORB returned by this method is not the singleton ORB returned
     * from the init() method.  Each call to this method returns
     * a new ORB instance initialized with the specified properties.
     */
    public static ORB init(Properties props) {
        _init_properties = props;
        org.omg.CORBA.ORB orb = initOrb(props.get(ORB_CLASS_KEY));

        orb.set_parameters(props);

        return orb;
    }

    abstract protected void set_parameters(Properties props);

    public void connect(org.omg.CORBA.Object obj) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public void disconnect(org.omg.CORBA.Object obj) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    abstract public String[] list_initial_services();

    abstract public org.omg.CORBA.Object resolve_initial_references(
            String object_name)
            throws org.omg.CORBA.ORBPackage.InvalidName;

    abstract public String object_to_string(org.omg.CORBA.Object obj);

    abstract public org.omg.CORBA.Object string_to_object(String str);

    abstract public NVList create_list(int count);

    public NVList create_operation_list(org.omg.CORBA.Object oper) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    abstract public NamedValue create_named_value(String s, Any any, int flags);

    abstract public ExceptionList create_exception_list();

    abstract public ContextList create_context_list();

    abstract public Context get_default_context();

    abstract public Environment create_environment();

    abstract public org.omg.CORBA.portable.OutputStream create_output_stream();

    abstract public void send_multiple_requests_oneway(Request[] req);

    abstract public void send_multiple_requests_deferred(Request[] req);

    abstract public boolean poll_next_response();

    abstract public Request get_next_response() throws WrongTransaction;

    abstract public TypeCode get_primitive_tc(TCKind tcKind);

    abstract public TypeCode create_struct_tc(String id, String name,
            StructMember[] members);

    abstract public TypeCode create_union_tc(String id, String name,
            TypeCode discriminator_type,
            UnionMember[] members);

    abstract public TypeCode create_enum_tc(String id, String name,
            String[] members);

    abstract public TypeCode create_alias_tc(String id, String name,
            TypeCode original_type);

    abstract public TypeCode create_exception_tc(String id, String name,
            StructMember[] members);

    abstract public TypeCode create_interface_tc(String id, String name);

    abstract public TypeCode create_string_tc(int bound);

    abstract public TypeCode create_wstring_tc(int bound);

    abstract public TypeCode create_sequence_tc(int bound,
            TypeCode element_type);

    abstract public TypeCode create_recursive_sequence_tc(int bound, int offset);

    abstract public TypeCode create_array_tc(int length, TypeCode element_type);

    public org.omg.CORBA.TypeCode create_native_tc(String id,
            String name) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public org.omg.CORBA.TypeCode create_abstract_interface_tc(
            String id,
            String name) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public org.omg.CORBA.TypeCode create_fixed_tc(short digits, short scale) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public org.omg.CORBA.TypeCode create_value_tc(String id,
            String name,
            short type_modifier,
            TypeCode concrete_base,
            ValueMember[] members) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public org.omg.CORBA.TypeCode create_recursive_tc(String id) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public org.omg.CORBA.TypeCode create_value_box_tc(String id,
            String name,
            TypeCode boxed_type) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    abstract public Any create_any();

    public org.omg.CORBA.Current get_current() {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public void run() {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public void shutdown(boolean wait_for_completion) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public boolean work_pending() {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public void perform_work() {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public boolean get_service_information(short service_type,
            ServiceInformationHolder service_info) {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }

    public org.omg.CORBA.Policy create_policy(int type, org.omg.CORBA.Any val)
            throws org.omg.CORBA.PolicyError {
        throw new org.omg.CORBA.NO_IMPLEMENT();
    }
}

